﻿Imports System.Xml
Imports System.Management
Imports System.IO

Module modDiskSpaceReporter

  'Declare and Initiatize Program-Level Variables and Constants
  Public arlComputers As New ArrayList
  Public arlDetectedDrives As New ArrayList
  Public intPollingInterval As Integer
  Public intPollingValue As Integer

  ''' <summary>
  ''' Loads the options in the Options file into memory
  ''' </summary>
  ''' <param name="fileName">The path and filename of the options file</param>
  Public Sub LoadComputersCollection(ByVal fileName As String)
    Try
      Dim m_xmld As XmlDocument
      Dim m_nodelist As XmlNodeList
      Dim m_node As XmlNode
      m_xmld = New XmlDocument()

      'Clear arlComputers ArrayList
      arlComputers.Clear()

      'Load the Xml file
      m_xmld.Load(fileName)

      'Get the list of computer nodes
      m_nodelist = m_xmld.SelectNodes("/options/computers/computer")

      'Loop through the nodes
      For Each m_node In m_nodelist
        Dim strComputerInfo() As String = {m_node.ChildNodes.Item(0).InnerText, m_node.ChildNodes.Item(1).InnerText, m_node.ChildNodes.Item(2).InnerText, ""}
        arlComputers.Add(strComputerInfo)
      Next

      'Get the list of polling nodes
      m_nodelist = m_xmld.SelectNodes("/options/polling")

      'Loop through the nodes
      For Each m_node In m_nodelist
        intPollingInterval = m_node.ChildNodes.Item(0).InnerText
        intPollingValue = m_node.ChildNodes.Item(1).InnerText
      Next
    Catch ex As Exception
      MessageBox.Show("There was an error loading the Options file.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1)
    End Try
  End Sub

  ''' <summary>
  ''' Returns a Boolean value whether of not the specified computer was successfully contacted
  ''' </summary>
  ''' <param name="strComputerName">The name of the computer to be contacted</param>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function PingComputer(ByVal strComputerName As String) As Boolean
    Try
      'Ping the computer and return whether or not the ping was successful
      Return My.Computer.Network.Ping(strComputerName, 500)
    Catch ex As Exception
      'If there was an error while pinging the computer, return FALSE
      Return False
    End Try
  End Function

  ''' <summary>
  ''' Checks the sizes of the computers in the Computers arraylist and notifies the computer user
  ''' which computers have fallen below the alert size
  ''' </summary>
  ''' <remarks></remarks>
  Public Sub CheckSizes()
    'Declare and Initialize Procedure-Level Variables
    Dim strMOSString As String = String.Empty
    Dim intComputerPos As Integer = 0
    Dim blnDetectedDrives As Boolean = False

    Try
      'Stop the timer.
      frmMain.tmrDiskSpaceReporter.Stop()

      'Clear the Detected Drives arraylist
      arlDetectedDrives.Clear()

      'Loop through the computers
      For i As Integer = 0 To arlComputers.Count - 1
        'Get the next computer info from Computers arraylist
        Dim strComputerInfo() As String = arlComputers.Item(i)
        Dim blnComputerOnline As Boolean

        If strComputerInfo(0).Trim = "(local)" Then     'If the computer is the one running the program
          strMOSString = "root\CIMV2"
          blnComputerOnline = True
        Else     'If the computer is not the one running the program
          strMOSString = "\\" & strComputerInfo(0) & "\root\CIMV2"
          blnComputerOnline = PingComputer(strComputerInfo(0))
        End If

        If blnComputerOnline = "True" Then     'Check the computer only if it is online
          'Query the computer drive specified and check its free speace against the specified alert value
          Dim searcher As New ManagementObjectSearcher(strMOSString, "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID='" & strComputerInfo(1).Trim & ":'")
          For Each queryObj As ManagementObject In searcher.Get()
            'Set the free space of the queried computer
            Dim dblRealFreeSpace As Double = CType(queryObj.Item("FreeSpace"), Double)
            'Get the alert value and convert it to bytes
            Dim dblMinFreeSpace As Double = (CType(strComputerInfo(2).Trim, Double) * 1024 * 1024)
            'Set the free space for display in the options window
            strComputerInfo(3) = Convert.ToString(Math.Round(dblRealFreeSpace / 1024 / 1024, 1))
            'If the free space is less than the alert size, then add the computer to the Detected Drives arraylist
            'and set the blnDetectedDrives variable to TRUE
            If dblRealFreeSpace < dblMinFreeSpace Then
              arlDetectedDrives.Add(strComputerInfo)
              blnDetectedDrives = True
            End If
          Next
        Else     'Set the free space to unreachable if computer cannot be pinged
          strComputerInfo(3) = "Unreachable"
        End If
        'Replace the computer info in Computers arraylist at its current position
        arlComputers.Item(i) = strComputerInfo
      Next

      'Set the interval and start the timer
      frmMain.tmrDiskSpaceReporter.Interval = intPollingInterval
      frmMain.tmrDiskSpaceReporter.Start()

      'If a drive was detected as being below its alert size, show the alert window
      If blnDetectedDrives Then
        frmAlertWindow.Show()
      End If
    Catch ex As Exception
      MessageBox.Show("There was an error while checking the drives.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1)
    End Try
  End Sub

  ''' <summary>
  ''' Creates the Options file
  ''' </summary>
  ''' <param name="blnDefault">Boolean value determining whether or not to create default options file or save options</param>
  ''' <returns>Boolean value regarding success of the file creation</returns>
  ''' <remarks>
  ''' Function serves two purposes.
  ''' 1) It creates the default options file if one cannot be found.
  ''' 2) It saves the options when the Options window is closed.
  ''' </remarks>
  Public Function CreateOptionsFile(Optional ByVal blnDefault As Boolean = True) As Boolean
    Dim m_xmld As New XmlTextWriter(Application.StartupPath & "\dsrOptions.xml", System.Text.Encoding.UTF8)
    Try
      With m_xmld
        .Formatting = Formatting.Indented
        .Indentation = 3
        .WriteStartDocument()
        .WriteStartElement("options")
        .WriteStartElement("computers")
        If blnDefault = True Then
          .WriteStartElement("computer")
          .WriteStartElement("name")
          .WriteString("(local)")     'computer name
          .WriteEndElement()
          .WriteStartElement("drive")
          .WriteString("C")     'drive letter
          .WriteEndElement()
          .WriteStartElement("alert")
          .WriteString("512")     'alert size in MB
          .WriteEndElement()     'alert
          .WriteEndElement()     'computer
        Else
          For i As Integer = 0 To arlComputers.Count - 1
            Dim strComputerInfo() As String = arlComputers.Item(i)
            .WriteStartElement("computer")
            .WriteStartElement("name")
            .WriteString(strComputerInfo(0).ToString)     'computer name
            .WriteEndElement()
            .WriteStartElement("drive")
            .WriteString(strComputerInfo(1).ToString)     'drive letter
            .WriteEndElement()
            .WriteStartElement("alert")
            .WriteString(strComputerInfo(2).ToString)     'alert size in MB
            .WriteEndElement()     'alert
            .WriteEndElement()     'computer
          Next
        End If
        .WriteEndElement() 'computers
        .WriteStartElement("polling")
        .WriteStartElement("interval")
        If blnDefault = True Then
          .WriteString("900000")
        Else
          .WriteString(intPollingInterval.ToString)
        End If
        .WriteEndElement()     'interval
        .WriteStartElement("value")
        If blnDefault = True Then
          .WriteString("2")
        Else
          .WriteString(intPollingValue.ToString)
        End If
        .WriteEndElement()     'value
        .WriteEndElement()     'polling
        .WriteEndElement()     'options
        .Close()
      End With
      Dim f As New FileInfo(Application.StartupPath & "\dsrOptions.xml")
      Return f.Exists
    Catch ex As Exception
      Return False
    End Try
  End Function

  ''' <summary>
  ''' Imports or exports Options file
  ''' </summary>
  ''' <param name="blnImport">Boolean value determining whether to import or export options file</param>
  ''' <returns>Boolean value regarding success of the file creation</returns>
  ''' <remarks>
  ''' Function serves two purposes.
  ''' 1) Imports an options file
  ''' 2) Exports an options file
  ''' </remarks>
  Public Function ImportExportOptionsFile(Optional ByVal blnImport As Boolean = True) As Boolean
    'Declare and Initialize Procedure-Level Variables
    Dim srdImportFile As StreamReader
    Dim srdExportFile As StreamWriter

    Try
      If blnImport = True Then     'If importing an options file
        'Open an instance of the OpenFileDialog
        With frmOptions.ofdOptions
          If .ShowDialog() = Windows.Forms.DialogResult.OK Then     'If a file was selected...
            'Open file selected from ofdOptions for reading
            srdImportFile = File.OpenText(.FileName)
            'Open export file for writing
            srdExportFile = File.CreateText(Application.StartupPath & "\dsrOptions.xml")
            'Write each line from the import file to export file
            Do Until srdImportFile.Peek = -1
              srdExportFile.WriteLine(srdImportFile.ReadLine())
            Loop
            'Close file selected from ofdOptions
            srdImportFile.Close()
            'Close export file
            srdExportFile.Close()
          Else     'If no file was selected...
            MessageBox.Show("You selected no file.", Application.ProductName & ": Error", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1)
            Exit Function
          End If
        End With
        Return True
      Else     'If exporting an options file
        'Open an instance of the SaveFileDialog
        With frmOptions.sfdOptions
          If .ShowDialog() = Windows.Forms.DialogResult.OK Then     'If a file was selected...
            'Open export file for writing
            srdExportFile = File.CreateText(.FileName)
            'Open file selected from ofdOptions for reading
            srdImportFile = File.OpenText(Application.StartupPath & "\dsrOptions.xml")
            'Write each line from the import file to export file
            Do Until srdImportFile.Peek = -1
              srdExportFile.WriteLine(srdImportFile.ReadLine())
            Loop
            'Close file selected from sfdOptions
            srdImportFile.Close()
            'Close export file
            srdExportFile.Close()
          Else     'If no file was selected...
            MessageBox.Show("You selected no file.", Application.ProductName & ": Error", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1)
            Exit Function
          End If
        End With
        Return True
      End If
    Catch ex As Exception
      MessageBox.Show(ex.Message.ToString)
      'Return False
    End Try
  End Function

End Module
